﻿using HML.Design;
using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Design;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
using HML;
using System.Reflection;

namespace HML
{
    /// <summary>
    /// 仪表控件
    /// </summary>
    [Description("仪表控件")]
    [DefaultProperty("Value")]
    [DefaultEvent("ValueChanged")]
    [TypeConverter(typeof(PropertyOrderConverter))]
    [Designer(typeof(MeterDesigner))]
    [ToolboxItem(true)]
    [ToolboxBitmap(typeof(Meter), "Controls.Meter.Resources.Meter.bmp")]
    public class Meter : MainThreadAnimationControl, ISkinObject
    {
        #region 主题

        private SkinObjectXmlMetadata skinObjectXmlMetadata = null;
        /// <summary>
        /// 主题对象在主题文件信息
        /// </summary>
        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public virtual SkinObjectXmlMetadata SkinObjectXmlMetadata
        {
            get
            {
                if (this.skinObjectXmlMetadata == null)
                    this.skinObjectXmlMetadata = new SkinObjectXmlMetadata(Assembly.GetAssembly(typeof(Meter)).GetName().Name, typeof(Meter).Name);

                return this.skinObjectXmlMetadata;
            }
        }

        private SkinController skinController = null;
        /// <summary>
        /// 主题控制器
        /// </summary>
        [Description("主题控制器")]
        [Category("杂项")]
        [PropertyOrder(-360)]
        [DefaultValue(null)]
        [RefreshProperties(RefreshProperties.All)]
        public virtual SkinController SkinController
        {
            get { return this.skinController; }
            set
            {
                if (this.skinController == value)
                    return;

                if (this.skinController != null)
                    this.skinController.RemoveSkinObject(this);

                this.skinController = value;

                if (this.skinController != null)
                    this.skinController.AddSkinObject(this);
            }
        }

        private SkinEnabledState skinEnabled= SkinEnabledState.Auto;
        /// <summary>
        /// 主题是否启用
        /// </summary>
        [Description("主题是否启用")]
        [Category("杂项")]
        [PropertyOrder(-300)]
        [DefaultValue(SkinEnabledState.Auto)]
        [RefreshProperties(RefreshProperties.All)]
        public virtual SkinEnabledState SkinEnabled
        {
            get { return this.skinEnabled; }
            set
            {
                if (this.skinEnabled == value)
                    return;

                this.skinEnabled = value;
                this.OnSkinChanged();
            }
        }

        private SkinStyle skinStyle = SkinStyle.Normal;
        /// <summary>
        /// 主题风格
        /// </summary>
        [Description("主题风格")]
        [Category("杂项")]
        [PropertyOrder(-260)]
        [DefaultValue(SkinStyle.Normal)]
        [RefreshProperties(RefreshProperties.All)]
        public virtual SkinStyle SkinStyle
        {
            get { return this.skinStyle; }
            set
            {
                if (this.skinStyle == value)
                    return;

                this.skinStyle = value;
                this.OnSkinChanged();
            }
        }

        private StyleAppearanceObject stateAppearance;
        /// <summary>
        /// 风格外观
        /// </summary>
        [Description("风格外观")]
        [Category("杂项")]
        [PropertyOrder(-200)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public StyleAppearanceObject StyleAppearance
        {
            get
            {
                if (this.stateAppearance == null)
                    this.stateAppearance = new StyleAppearanceObject(this, null);
                return this.stateAppearance;
            }
        }

        /// <summary>
        /// 主题已更改
        /// </summary>
        public virtual void OnSkinChanged()
        {
            SkinManager.SyncSkinValueToProperty(this);
            this.Invalidate();
        }

        private ISkinObject followSkinObject = null;
        /// <summary>
        /// 主题设置跟随指定主题对象（自己的设置不再生效，提供给代码使用）
        /// </summary>
        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        [Localizable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public virtual ISkinObject FollowSkinObject
        {
            get { return this.followSkinObject; }
            set
            {
                if (this.followSkinObject == value)
                    return;

                this.followSkinObject = value;
                this.OnSkinChanged();
            }
        }

        public virtual bool GetSkinObjectSkinStateCore()
        {
            return SkinManager.GetSkinObjectSkinState(this.FollowSkinObject ?? this);
        }

        void ISkinObject.InitializeInvalidate()
        {
            throw new NotImplementedException();
        }

        void ISkinObject.Invalidate()
        {
            this.Invalidate();
        }

        #endregion

        #region 新增事件

        private static readonly object EventValueChanged = new object();
        /// <summary>
        /// Value值更改事件
        /// </summary>
        [Description("Value值更改事件")]
        public event EventHandler ValueChanged
        {
            add { Events.AddHandler(EventValueChanged, value); }
            remove { Events.RemoveHandler(EventValueChanged, value); }
        }

        private static readonly object EventValueOverflow = new object();
        /// <summary>
        /// Value值溢出事件
        /// </summary>
        [Description("Value值溢出事件")]
        public event EventHandler ValueOverflow
        {
            add { Events.AddHandler(EventValueOverflow, value); }
            remove { Events.RemoveHandler(EventValueOverflow, value); }
        }

        #endregion

        #region 停用事件

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event EventHandler PaddingChanged
        {
            add { base.PaddingChanged += value; }
            remove { base.PaddingChanged -= value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event KeyEventHandler KeyDown
        {
            add { base.KeyDown += value; }
            remove { base.KeyDown -= value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event KeyEventHandler KeyUp
        {
            add { base.KeyUp += value; }
            remove { base.KeyUp -= value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event KeyPressEventHandler KeyPress
        {
            add { base.KeyPress += value; }
            remove { base.KeyPress -= value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event PreviewKeyDownEventHandler PreviewKeyDown
        {
            add { base.PreviewKeyDown += value; }
            remove { base.PreviewKeyDown -= value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event EventHandler TabIndexChanged
        {
            add { base.TabIndexChanged += value; }
            remove { base.TabIndexChanged -= value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event EventHandler TabStopChanged
        {
            add { base.TabStopChanged += value; }
            remove { base.TabStopChanged -= value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event EventHandler TextChanged
        {
            add { base.TextChanged += value; }
            remove { base.TextChanged -= value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event EventHandler FontChanged
        {
            add { base.FontChanged += value; }
            remove { base.FontChanged -= value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event EventHandler RightToLeftChanged
        {
            add { base.RightToLeftChanged += value; }
            remove { base.RightToLeftChanged -= value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event EventHandler ImeModeChanged
        {
            add { base.ImeModeChanged += value; }
            remove { base.ImeModeChanged -= value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event EventHandler BackgroundImageChanged
        {
            add { base.BackgroundImageChanged += value; }
            remove { base.BackgroundImageChanged -= value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event EventHandler BackgroundImageLayoutChanged
        {
            add { base.BackgroundImageLayoutChanged += value; }
            remove { base.BackgroundImageLayoutChanged -= value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event EventHandler BackColorChanged
        {
            add { base.BackColorChanged += value; }
            remove { base.BackColorChanged -= value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event EventHandler ForeColorChanged
        {
            add { base.ForeColorChanged += value; }
            remove { base.ForeColorChanged -= value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event EventHandler Click
        {
            add { base.Click += value; }
            remove { base.Click -= value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event EventHandler DoubleClick
        {
            add { base.DoubleClick += value; }
            remove { base.DoubleClick -= value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event MouseEventHandler MouseClick
        {
            add { base.MouseClick += value; }
            remove { base.MouseClick -= value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event MouseEventHandler MouseDoubleClick
        {
            add { base.MouseDoubleClick += value; }
            remove { base.MouseDoubleClick -= value; }
        }

        #endregion

        #region 新增属性

        private bool animationEnabled = false;
        /// <summary>
        /// Value改变时是否采用动画方式
        /// </summary>
        [Description("Value改变时是否采用动画方式")]
        [Category("杂项")]
        [PropertyOrder(-198)]
        [DefaultValue(false)]
        public bool AnimationEnabled
        {
            get { return this.animationEnabled; }
            set
            {
                if (this.animationEnabled == value)
                    return;

                this.animationEnabled = value;
                if (!this.animationEnabled)
                {
                    this.animation_current_value = this.Value;
                    MainThreadAnimationControl.AnimationStop(this);
                    this.Invalidate();
                }
            }
        }

        private int animationTime = 150;
        /// <summary>
        /// Value改变时使用动画的时间(毫秒)
        /// </summary>
        [Description("Value改变时使用动画的时间(毫秒)")]
        [Category("杂项")]
        [PropertyOrder(-196)]
        [DefaultValue(150)]
        public int AnimationTime
        {
            get { return this.animationTime; }
            set
            {
                if (this.animationTime == value || value <= 0)
                    return;

                this.animationTime = value;
            }
        }

        private PlateObject plate;
        /// <summary>
        /// 表盘
        /// </summary>
        [Description("表盘")]
        [Category("杂项")]
        [PropertyOrder(-195)]
        [DefaultValue(null)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public PlateObject Plate
        {
            get
            {
                if (this.plate == null)
                    this.plate = new PlateObject(this);
                return this.plate;
            }
        }

        private ArcObject arc;
        /// <summary>
        /// 弧
        /// </summary>
        [Description("弧")]
        [Category("杂项")]
        [PropertyOrder(-194)]
        [DefaultValue(null)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public ArcObject Arc
        {
            get
            {
                if (this.arc == null)
                    this.arc = new ArcObject(this);
                return this.arc;
            }
        }

        private GradualArcObject gradualArc;
        /// <summary>
        /// 渐变弧
        /// </summary>
        [Description("渐变弧")]
        [Category("杂项")]
        [PropertyOrder(-192)]
        [DefaultValue(null)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public GradualArcObject GradualArc
        {
            get
            {
                if (this.gradualArc == null)
                    this.gradualArc = new GradualArcObject(this);
                return this.gradualArc;
            }
        }

        private PointerObject pointer;
        /// <summary>
        /// 指针
        /// </summary>
        [Description("指针")]
        [Category("杂项")]
        [PropertyOrder(-190)]
        [DefaultValue(null)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public PointerObject Pointer
        {
            get
            {
                if (this.pointer == null)
                    this.pointer = new PointerObject(this);
                return this.pointer;
            }
        }

        private MarkObject mark;
        /// <summary>
        /// 刻度
        /// </summary>
        [Description("刻度")]
        [Category("杂项")]
        [PropertyOrder(-188)]
        [DefaultValue(null)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public MarkObject Mark
        {
            get
            {
                if (this.mark == null)
                    this.mark = new MarkObject(this);
                return this.mark;
            }
        }

        private int places = 0;
        /// <summary>
        /// 保留位数
        /// </summary>
        [Description("保留位数")]
        [Category("杂项")]
        [PropertyOrder(-186)]
        [DefaultValue(0)]
        public int Places
        {
            get { return this.places; }
            set
            {
                if (this.places == value)
                    return;

                this.places = value;
                this.Invalidate();
            }
        }

        private bool allowOverflow = false;
        /// <summary>
        /// 是否允许Value值溢出显示
        /// </summary>
        [Description("是否允许Value值溢出显示")]
        [Category("杂项")]
        [PropertyOrder(-184)]
        [DefaultValue(false)]
        public bool AllowOverflow
        {
            get { return this.allowOverflow; }
            set
            {
                if (this.allowOverflow == value)
                    return;

                this.allowOverflow = value;
            }
        }

        private bool valueVisible = true;
        /// <summary>
        /// 是否显示值文本
        /// </summary>
        [Description("是否显示值文本")]
        [Category("杂项")]
        [PropertyOrder(-182)]
        [DefaultValue(true)]
        public bool ValueVisible
        {
            get { return this.valueVisible; }
            set
            {
                if (this.valueVisible == value)
                    return;

                this.valueVisible = value;
                this.Invalidate();
            }
        }

        private int valueDistance = 0;
        /// <summary>
        /// 值文本与仪表垂直方向间距
        /// </summary>
        [Description("值文本与仪表垂直方向间距")]
        [Category("杂项")]
        [PropertyOrder(-180)]
        [DefaultValue(0)]
        public int ValueDistance
        {
            get { return this.valueDistance; }
            set
            {
                if (this.valueDistance == value)
                    return;

                this.valueDistance = value;
                this.Invalidate();
            }
        }

        private double maxValue = 100D;
        /// <summary>
        /// 最大值
        /// </summary>
        [Description("最大值")]
        [Category("杂项")]
        [PropertyOrder(-178)]
        [DefaultValue(100D)]
        public double MaxValue
        {
            get { return this.maxValue; }
            set
            {
                if (this.maxValue == value)
                    return;

                this.maxValue = value;
                if (value < this.minValue)
                {
                    this.minValue = value;
                }
                if (this.value < this.minValue)
                {
                    this.value = this.minValue;
                }
                if (this.value > this.maxValue)
                {
                    this.value = this.maxValue;
                }

                this.animation_current_value = this.Value;
                MainThreadAnimationControl.AnimationStop(this);
                this.Invalidate();

            }
        }

        private double minValue = 0D;
        /// <summary>
        /// 最小值
        /// </summary>
        [Description("最小值")]
        [Category("杂项")]
        [PropertyOrder(-176)]
        [DefaultValue(0D)]
        public double MinValue
        {
            get { return this.minValue; }
            set
            {
                if (this.minValue == value)
                    return;

                this.minValue = value;
                if (value > this.maxValue)
                {
                    this.maxValue = value;
                }
                if (this.value < this.minValue)
                {
                    this.value = this.minValue;
                }
                if (this.value > this.maxValue)
                {
                    this.value = this.maxValue;
                }

                this.animation_current_value = this.Value;
                MainThreadAnimationControl.AnimationStop(this);
                this.Invalidate();
            }
        }

        private double value = 0D;
        /// <summary>
        /// 值
        /// </summary>
        [Description("值")]
        [Category("杂项")]
        [PropertyOrder(-174)]
        [DefaultValue(0D)]
        public double Value
        {
            get { return this.value; }
            set
            {
                if (this.AllowOverflow)
                {
                    if (this.value == value)
                        return;

                    double value_tmp = Math.Max(Math.Min(value, this.MaxValue), this.MinValue);

                    this.value = value;
                    if (this.AnimationEnabled && this.Enabled && this.Visible && this.DesignMode == false && this.Parent != null)
                    {
                        this.animation_start_value = this.animation_current_value;
                        this.animation_current_value = this.animation_start_value;
                        this.animation_end_value = value_tmp;

                        this.usedTime = 0;
                        MainThreadAnimationControl.AnimationStart(this);
                        this.Invalidate();
                    }
                    else
                    {
                        this.animation_current_value = value_tmp;
                        this.Invalidate();
                    }

                    this.OnValueChanged(EventArgs.Empty);

                    if (value_tmp != value)
                    {
                        this.OnValueOverflow(EventArgs.Empty);
                    }
                }
                else
                {
                    value = Math.Min(value, this.MaxValue);
                    value = Math.Max(value, this.MinValue);
                    if (this.value == value)
                        return;

                    this.value = value;
                    if (this.AnimationEnabled && this.Enabled && this.Visible && this.DesignMode == false && this.Parent != null)
                    {
                        this.animation_start_value = this.animation_current_value;
                        this.animation_current_value = this.animation_start_value;
                        this.animation_end_value = value;

                        this.usedTime = 0;
                        MainThreadAnimationControl.AnimationStart(this);
                        this.Invalidate();
                    }
                    else
                    {
                        this.animation_current_value = value;
                        this.Invalidate();
                    }

                    this.OnValueChanged(EventArgs.Empty);
                }
            }
        }

        #endregion

        #region 重写属性

        protected override Size DefaultSize
        {
            get { return new Size(210, 160); }
        }

        protected override ImeMode DefaultImeMode
        {
            get { return ImeMode.Disable; }
        }

        #endregion

        #region 停用属性

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public new Padding Padding
        {
            get { return base.Padding; }
            set { base.Padding = value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new int TabIndex
        {
            get { return base.TabIndex; }
            set { base.TabIndex = value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public new bool TabStop
        {
            get { return base.TabStop; }
            set { base.TabStop = value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public override string Text
        {
            get { return base.Text; }
            set { base.Text = value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public override RightToLeft RightToLeft
        {
            get { return base.RightToLeft; }
            set { base.RightToLeft = value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new ImeMode ImeMode
        {
            get { return base.ImeMode; }
            set { base.ImeMode = value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public override Image BackgroundImage
        {
            get { return base.BackgroundImage; }
            set { base.BackgroundImage = value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public override ImageLayout BackgroundImageLayout
        {
            get { return base.BackgroundImageLayout; }
            set { base.BackgroundImageLayout = value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public override Color BackColor
        {
            get { return this.StyleAppearance.BackColor; }
            set { }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public override Color ForeColor
        {
            get { return this.StyleAppearance.TextColor; }
            set { }
        }

        #endregion

        #region 字段

        /// <summary>
        /// 动画开始值
        /// </summary>
        private double animation_start_value = 0f;
        /// <summary>
        /// 动画结束值
        /// </summary>
        private double animation_end_value = 0f;
        /// <summary>
        /// 动画当前值
        /// </summary>
        private double animation_current_value = 0f;
        /// <summary>
        /// 动画已使用的时间
        /// </summary>
        private double usedTime = 0;

        /// <summary>
        /// 仪表弧度大小
        /// </summary>
        private int arcAngleSize = 180;

        #endregion

        public Meter()
        {
            SetStyle(ControlStyles.UserPaint, true);
            SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
            SetStyle(ControlStyles.ResizeRedraw, true);
            SetStyle(ControlStyles.SupportsTransparentBackColor, true);
            SetStyle(ControlStyles.StandardClick, false);
            SetStyle(ControlStyles.StandardDoubleClick, false);
            SetStyle(ControlStyles.Selectable, false);

            this.TabStop = false;
            this.OnSkinChanged();
        }

        #region 重写

        protected override void OnScaleDpiChangedInitialize()
        {
            this.Invalidate();
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);

            Graphics g = e.Graphics;
            g.SmoothingMode = SmoothingMode.AntiAlias;

            Size scale_pointerSize = new SizeF(this.Pointer.Size.Width * this.ScaleDpi, this.Pointer.Size.Height * this.ScaleDpi).ToSize();
            int scale_arcThickness = this.ValueVisible ? (int)Math.Ceiling(this.Arc.Thickness * this.ScaleDpi) : 0;
            int scale_gradualThickness = this.GradualArc.Visible ? (int)Math.Ceiling(this.GradualArc.Thickness * this.ScaleDpi) : 0;
            Size scale_markMainLineSize = new SizeF(this.Mark.MainLineSize.Width * this.ScaleDpi, this.Mark.MainLineSize.Height * this.ScaleDpi).ToSize();
            Size scale_markMinorLineSize = new SizeF(scale_markMainLineSize.Width / 2f, scale_markMainLineSize.Height / 5f * 3).ToSize();
            int scale_markMainTextMargin = (int)Math.Ceiling(this.Mark.MainTextDistance * this.ScaleDpi);
            int scale_plateOutBorderThickness = (int)Math.Ceiling(this.Plate.OutBorderThickness * this.ScaleDpi);
            int scale_plateInnerBorderThickness = (int)Math.Ceiling(this.Plate.InnerBorderThickness * this.ScaleDpi);
            int scale_valueBottomSpacing = (int)Math.Ceiling(2 * this.ScaleDpi);

            int meter_top_height = this.GetMeterTopHeight();
            int meter_bottom_height = this.GetMeterBottomHeight();
            RectangleF meter_rect = new RectangleF(this.ClientRectangle.X + this.ClientRectangle.Width / 2 - meter_top_height, this.ClientRectangle.Y + this.ClientRectangle.Height / 2 - meter_top_height, meter_top_height * 2, meter_top_height * 2);
            PointF meter_center = new PointF(meter_rect.X + meter_rect.Width / 2f, meter_rect.Y + meter_rect.Height / 2f + (meter_top_height - meter_bottom_height) / 2);
            float start_angle = 90 + (180 - this.arcAngleSize / 2f);//绘制开始角度
            decimal proportion = ((decimal)this.animation_current_value - (decimal)this.MinValue) / ((decimal)this.MaxValue - (decimal)this.MinValue);

            //表盘
            int pie_bottom_radian_left_right_height = meter_bottom_height + scale_valueBottomSpacing;//扇形底部左右圆弧高度

            // 外边框
            GraphicsPath out_border_gp = new GraphicsPath();
            RectangleF out_border_rect = new RectangleF(meter_center.X - meter_rect.Width / 2 - scale_markMainTextMargin - scale_plateInnerBorderThickness - scale_plateOutBorderThickness, meter_center.Y - meter_rect.Height / 2 - scale_markMainTextMargin - scale_plateInnerBorderThickness - scale_plateOutBorderThickness, meter_rect.Width + scale_markMainTextMargin * 2 + scale_plateInnerBorderThickness * 2 + scale_plateOutBorderThickness * 2, meter_rect.Height + scale_markMainTextMargin * 2 + scale_plateInnerBorderThickness * 2 + scale_plateOutBorderThickness * 2);
            out_border_gp.AddArc(out_border_rect, 180, 180);

            RectangleF out_border_right_rect = new RectangleF(out_border_rect.Right - pie_bottom_radian_left_right_height * 2, out_border_rect.Y + out_border_rect.Height / 2 - pie_bottom_radian_left_right_height - pie_bottom_radian_left_right_height / 4, pie_bottom_radian_left_right_height * 2, pie_bottom_radian_left_right_height * 2 + pie_bottom_radian_left_right_height / 2);
            out_border_gp.AddArc(out_border_right_rect, 0, 90);

            RectangleF out_border_left_rect = new RectangleF(out_border_rect.X, out_border_rect.Y + out_border_rect.Height / 2 - pie_bottom_radian_left_right_height - pie_bottom_radian_left_right_height / 4, pie_bottom_radian_left_right_height * 2, pie_bottom_radian_left_right_height * 2 + pie_bottom_radian_left_right_height / 2);
            out_border_gp.AddArc(out_border_left_rect, 90, 90);
            out_border_gp.CloseAllFigures();

            LinearGradientBrush out_border_lgb = new LinearGradientBrush(out_border_rect, Color.White, this.StyleAppearance.Plate.OutBorderColor, 45);
            g.FillPath(out_border_lgb, out_border_gp);
            out_border_lgb.Dispose();
            out_border_gp.Dispose();

            // 内边框
            GraphicsPath inner_border_gp = new GraphicsPath();
            RectangleF inner_border_rect = new RectangleF(meter_center.X - meter_rect.Width / 2 - scale_markMainTextMargin - scale_plateInnerBorderThickness / 2, meter_center.Y - meter_rect.Height / 2 - scale_markMainTextMargin - scale_plateInnerBorderThickness / 2, meter_rect.Width + scale_markMainTextMargin * 2 + scale_plateInnerBorderThickness, meter_rect.Height + scale_markMainTextMargin * 2 + scale_plateInnerBorderThickness);
            inner_border_gp.AddArc(inner_border_rect, 180, 180);

            RectangleF inner_border_right_rect = new RectangleF(inner_border_rect.Right - pie_bottom_radian_left_right_height * 2, inner_border_rect.Y + inner_border_rect.Height / 2 - pie_bottom_radian_left_right_height, pie_bottom_radian_left_right_height * 2, pie_bottom_radian_left_right_height * 2);
            inner_border_gp.AddArc(inner_border_right_rect, 0, 90);

            RectangleF inner_border_left_rect = new RectangleF(inner_border_rect.X, inner_border_rect.Y + inner_border_rect.Height / 2 - pie_bottom_radian_left_right_height, pie_bottom_radian_left_right_height * 2, pie_bottom_radian_left_right_height * 2);
            inner_border_gp.AddArc(inner_border_left_rect, 90, 90);
            inner_border_gp.CloseAllFigures();

            LinearGradientBrush inner_border_lgb = new LinearGradientBrush(inner_border_rect, Color.White, this.StyleAppearance.Plate.InnerBorderColor, 225);
            Pen inner_border_pen = new Pen(inner_border_lgb, scale_plateInnerBorderThickness + 1);
            g.DrawPath(inner_border_pen, inner_border_gp);
            inner_border_pen.Dispose();
            inner_border_lgb.Dispose();

            // 背景
            GraphicsPath back_gp = new GraphicsPath();
            RectangleF back_rect = new RectangleF(meter_center.X - meter_rect.Width / 2 - scale_markMainTextMargin, meter_center.Y - meter_rect.Height / 2 - scale_markMainTextMargin, meter_rect.Width + scale_markMainTextMargin * 2, meter_rect.Height + scale_markMainTextMargin * 2);
            back_gp.AddArc(back_rect, 180, 180);

            RectangleF back_right_rect = new RectangleF(back_rect.Right - pie_bottom_radian_left_right_height * 2, back_rect.Y + back_rect.Height / 2 - pie_bottom_radian_left_right_height, pie_bottom_radian_left_right_height * 2, pie_bottom_radian_left_right_height * 2);
            back_gp.AddArc(back_right_rect, 0, 90);

            RectangleF back_left_rect = new RectangleF(back_rect.X, back_rect.Y + back_rect.Height / 2 - pie_bottom_radian_left_right_height, pie_bottom_radian_left_right_height * 2, pie_bottom_radian_left_right_height * 2);
            back_gp.AddArc(back_left_rect, 90, 90);
            back_gp.CloseAllFigures();

            PathGradientBrush back_sb = new PathGradientBrush(back_gp) { SurroundColors = new Color[] { this.StyleAppearance.Plate.BackColor }, CenterColor = this.StyleAppearance.Plate.BackShadowColor, CenterPoint = new PointF(back_rect.X + back_rect.Width / 8, back_rect.Y + back_rect.Height / 8) };
            g.FillPath(back_sb, back_gp);
            back_sb.Dispose();
            back_gp.Dispose();


            // 弧
            if (this.Arc.Visible)
            {
                RectangleF value_arc_rect = new RectangleF(meter_center.X - scale_pointerSize.Height - scale_arcThickness / 2, meter_center.Y - scale_pointerSize.Height - scale_arcThickness / 2, scale_pointerSize.Height * 2 + scale_arcThickness, scale_pointerSize.Height * 2 + scale_arcThickness);

                //背景色
                Pen value_arc_pen = new Pen(this.StyleAppearance.Arc.BackColor, scale_arcThickness);
                g.DrawArc(value_arc_pen, value_arc_rect, start_angle, this.arcAngleSize);

                // 前景色
                value_arc_pen.Color = this.StyleAppearance.Arc.ValueColor;
                g.DrawArc(value_arc_pen, value_arc_rect, start_angle, (float)(this.arcAngleSize * proportion));

                value_arc_pen.Dispose();
            }

            // 渐变弧
            if (this.GradualArc.Visible && this.GradualArc.ColorItems.Count > 1)
            {
                PointF angle1 = ControlHelper.CalculatePointForAngle(meter_center, scale_pointerSize.Height + scale_arcThickness + scale_gradualThickness, 1);
                PointF angle2 = ControlHelper.CalculatePointForAngle(meter_center, scale_pointerSize.Height + scale_arcThickness + scale_gradualThickness, 2);
                Pen gradual_pen = new Pen(Color.White, (int)Math.Ceiling(Math.Sqrt(Math.Pow(Math.Abs(angle1.X - angle2.X), 2) + Math.Pow(Math.Abs(angle1.Y - angle2.Y), 2))) + 1);

                float item_current_angle = 0;
                float pen_current_angle;
                for (int i = 1; i < this.GradualArc.ColorItems.Count; i++)
                {
                    float color_angle = (float)this.arcAngleSize * (this.GradualArc.ColorItems[i].Position - this.GradualArc.ColorItems[i - 1].Position);

                    float rgb_r = (this.GradualArc.ColorItems[i].Color.R - this.GradualArc.ColorItems[i - 1].Color.R) / color_angle;
                    float rgb_g = (this.GradualArc.ColorItems[i].Color.G - this.GradualArc.ColorItems[i - 1].Color.G) / color_angle;
                    float rgb_b = (this.GradualArc.ColorItems[i].Color.B - this.GradualArc.ColorItems[i - 1].Color.B) / color_angle;

                    for (int k = 0; k < color_angle; k++)
                    {
                        gradual_pen.Color = Color.FromArgb(
                        ControlHelper.VerifyRGB((int)(this.GradualArc.ColorItems[i - 1].Color.R + rgb_r * k)),
                        ControlHelper.VerifyRGB((int)(this.GradualArc.ColorItems[i - 1].Color.G + rgb_g * k)),
                        ControlHelper.VerifyRGB((int)(this.GradualArc.ColorItems[i - 1].Color.B + rgb_b * k))
                        );
                        pen_current_angle = start_angle + item_current_angle + k;
                        PointF gradual_line_start_point = ControlHelper.CalculatePointForAngle(meter_center, scale_pointerSize.Height + scale_arcThickness, pen_current_angle);
                        PointF gradual_line_end_point = ControlHelper.CalculatePointForAngle(gradual_line_start_point, scale_gradualThickness, pen_current_angle);

                        g.DrawLine(gradual_pen, gradual_line_start_point, gradual_line_end_point);
                    }
                    item_current_angle += color_angle;
                }

                gradual_pen.Dispose();
            }

            if (this.MinValue >= this.MaxValue)
                goto value_draw;

            // 刻度
            Pen mark_main_line_pen = new Pen(this.StyleAppearance.Mark.MainLineColor, scale_markMainLineSize.Width) { EndCap = LineCap.Round };
            Pen mark_minor_line_pen = new Pen(this.StyleAppearance.Mark.MinorLineColor, scale_markMinorLineSize.Width) { EndCap = LineCap.Round };
            SolidBrush mark_main_text_sb = new SolidBrush(this.StyleAppearance.Mark.MainTextColor);

            int mark_main_count = (int)(Math.Abs((decimal)this.MaxValue - (decimal)this.MinValue) / (decimal)this.Mark.MainFrequency) + (Math.Abs((decimal)this.MaxValue - (decimal)this.MinValue) % (decimal)this.Mark.MainFrequency == 0 ? 0 : 1);
            decimal mark_main_angle_interval = (decimal)this.arcAngleSize / ((decimal)this.MaxValue - (decimal)this.MinValue) * (decimal)this.Mark.MainFrequency;
            decimal mark_minor_angle_interval = mark_main_angle_interval / this.Mark.MinorAmount;
            float mark_main_current_angle = start_angle;
            for (int i = 0; i <= mark_main_count; i++)
            {
                if (start_angle <= mark_main_current_angle && mark_main_current_angle <= start_angle + this.arcAngleSize)
                {
                    // 主刻度线
                    PointF mark_main_current_start_point = ControlHelper.CalculatePointForAngle(meter_center, scale_pointerSize.Height, mark_main_current_angle);
                    PointF mark_main_current_end_point = ControlHelper.CalculatePointForAngle(mark_main_current_start_point, scale_markMainLineSize.Height, mark_main_current_angle);
                    g.DrawLine(mark_main_line_pen, mark_main_current_start_point, mark_main_current_end_point);

                    // 主刻度文本
                    string mark_main_ext = ControlHelper.ReserveDecimals((Math.Min(this.MaxValue, (double)((decimal)this.MinValue + (decimal)this.Mark.MainFrequency * i))).ToString(), this.Places);
                    SizeF mark_main_text_size = g.MeasureString(mark_main_ext, this.Mark.MainTextFont, int.MaxValue, StringFormat.GenericTypographic);
                    PointF mark_main_text_point = this.ConvertTextPoint(ControlHelper.CalculatePointForAngle(meter_center, scale_pointerSize.Height + Math.Max(scale_arcThickness + scale_gradualThickness, scale_markMainLineSize.Height + scale_markMainLineSize.Width), mark_main_current_angle), mark_main_text_size, mark_main_current_angle);
                    g.DrawString(mark_main_ext, this.Mark.MainTextFont, mark_main_text_sb, mark_main_text_point, StringFormat.GenericTypographic);

                }
                // 子刻度线
                if (this.Mark.MinorAmount > 1)
                {
                    for (int k = 1; k < this.Mark.MinorAmount; k++)
                    {
                        float mark_minor_current_angle = mark_main_current_angle + (float)mark_minor_angle_interval * k;
                        if (start_angle <= mark_minor_current_angle && mark_minor_current_angle <= start_angle + this.arcAngleSize)
                        {
                            PointF mark_minor_current_start_point = ControlHelper.CalculatePointForAngle(meter_center, scale_pointerSize.Height, mark_minor_current_angle);
                            PointF mark_minor_current_end_point = ControlHelper.CalculatePointForAngle(mark_minor_current_start_point, scale_markMinorLineSize.Height, mark_minor_current_angle);
                            g.DrawLine(mark_minor_line_pen, mark_minor_current_start_point, mark_minor_current_end_point);
                        }
                    }
                }

                mark_main_current_angle += (float)mark_main_angle_interval;

            }

            mark_main_line_pen.Dispose();
            mark_minor_line_pen.Dispose();
            mark_main_text_sb.Dispose();


            // 指针
            float pointer_current_angle = start_angle + this.arcAngleSize * (float)(proportion);
            PointF pointer_current_end_point = ControlHelper.CalculatePointForAngle(meter_center, scale_pointerSize.Height, pointer_current_angle);
            PointF pointer_current_start_point = ControlHelper.CalculatePointForAngle(meter_center, scale_pointerSize.Width * 2.5f, pointer_current_angle + 180);

            Pen pointer_heart_pen = new Pen(this.StyleAppearance.Pointer.Color, scale_pointerSize.Width) { StartCap = LineCap.Round, EndCap = LineCap.Round };
            g.DrawLine(pointer_heart_pen, pointer_current_start_point, pointer_current_end_point);
            pointer_heart_pen.Dispose();

            //针帽
            RectangleF pointer_heart_rect = new RectangleF(meter_center.X - scale_pointerSize.Width / 2f * 3, meter_center.Y - scale_pointerSize.Width / 2f * 3, scale_pointerSize.Width * 3, scale_pointerSize.Width * 3);
            GraphicsPath pointer_heart_gp = new GraphicsPath();
            pointer_heart_gp.AddEllipse(pointer_heart_rect);

            PathGradientBrush pointer_heart_pgb = new PathGradientBrush(pointer_heart_gp) { SurroundColors = new Color[] { this.StyleAppearance.Pointer.CapColor }, CenterColor = this.StyleAppearance.Pointer.CapShadowColor, CenterPoint = new PointF(pointer_heart_rect.X + pointer_heart_rect.Width / 8, pointer_heart_rect.Y + pointer_heart_rect.Height / 8) };
            g.FillEllipse(pointer_heart_pgb, pointer_heart_rect);
            pointer_heart_pgb.Dispose();
            pointer_heart_gp.Dispose();

            Pen pointer_heart_border_pen = new Pen(this.StyleAppearance.Pointer.CapColor, 1);
            g.DrawEllipse(pointer_heart_border_pen, pointer_heart_rect);
            pointer_heart_border_pen.Dispose();

        value_draw:
            // 值文本
            if (this.ValueVisible)
            {
                string value_str = ControlHelper.ReserveDecimals(this.Value.ToString(), this.Places);
                Size value_size = Size.Ceiling(g.MeasureString(value_str, this.Font, int.MaxValue, StringFormat.GenericTypographic));

                SolidBrush value_sb = new SolidBrush(this.StyleAppearance.TextColor);
                g.DrawString(value_str, this.Font, value_sb, new PointF(meter_center.X - value_size.Width / 2, meter_center.Y + meter_bottom_height - value_size.Height), StringFormat.GenericTypographic);
                value_sb.Dispose();
            }

        }

        protected override void OnEnabledChanged(EventArgs e)
        {
            base.OnEnabledChanged(e);

            if (this.DesignMode)
                return;

            if (!this.Enabled)
            {
                this.animation_current_value = this.Value;
                MainThreadAnimationControl.AnimationStop(this);
            }
        }

        protected override void OnVisibleChanged(EventArgs e)
        {
            base.OnVisibleChanged(e);

            if (this.DesignMode)
                return;

            if (!this.Visible)
            {
                this.animation_current_value = this.Value;
                MainThreadAnimationControl.AnimationStop(this);
            }
        }

        protected override void OnParentChanged(EventArgs e)
        {
            base.OnParentChanged(e);

            if (this.DesignMode)
                return;

            if (!this.Visible)
            {
                this.animation_current_value = this.Value;
                MainThreadAnimationControl.AnimationStop(this);
            }
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                MainThreadAnimationControl.AnimationStop(this);
            }
            base.Dispose(disposing);
        }

        /// <summary>
        /// 动画控件动画中要处理的内容(不能时耗时操作)
        /// </summary>
        /// <param name="interval">动画定时器间隔时间</param>
        protected override void Animationing(int interval)
        {
            bool finish = false;
            this.usedTime += interval;
            if (this.usedTime > this.AnimationTime)
            {
                this.usedTime = this.AnimationTime;
                MainThreadAnimationControl.AnimationStop(this);
                finish = true;
            }

            double progress = this.usedTime / AnimationTime;
            if (finish)
            {
                if (progress < 0)
                    progress = 0;
                if (progress > 1)
                    progress = 1;

                this.usedTime = 0;
            }

            this.animation_current_value = this.animation_start_value + (this.animation_end_value - this.animation_start_value) * progress;
            this.Invalidate();
        }

        #endregion

        #region 虚方法

        protected virtual void OnValueChanged(EventArgs e)
        {
            EventHandler handler = Events[EventValueChanged] as EventHandler;
            if (handler != null)
            {
                handler(this, e);
            }
        }

        protected virtual void OnValueOverflow(EventArgs e)
        {
            EventHandler handler = Events[EventValueOverflow] as EventHandler;
            if (handler != null)
            {
                handler(this, e);
            }
        }

        #endregion

        #region 私有方法

        /// <summary>
        /// 获取仪表上半高度高度
        /// </summary>
        /// <returns></returns>
        private int GetMeterTopHeight()
        {
            int scale_pointerHeight = (int)Math.Ceiling(this.Pointer.Size.Height * this.ScaleDpi);
            int scale_arcThickness = (int)Math.Ceiling(this.Arc.Thickness * this.ScaleDpi);
            int scale_gradualThickness = (int)Math.Ceiling(this.GradualArc.Thickness * this.ScaleDpi);

            return scale_pointerHeight + scale_arcThickness + scale_gradualThickness + this.Mark.MainTextFont.Height;
        }

        /// <summary>
        /// 获取仪表下半高度高度
        /// </summary>
        /// <returns></returns>
        private int GetMeterBottomHeight()
        {
            int scale_valueDistance = (int)Math.Ceiling(this.ValueDistance * this.ScaleDpi);
            return (this.ValueVisible ? this.Font.Height + scale_valueDistance : 0) + this.Mark.MainTextFont.Height;
        }

        /// <summary>
        /// 转换文本坐标
        /// </summary>
        /// <param name="text_point">文本原始坐标</param>
        /// <param name="text_size">文本Size</param>
        /// <param name="text_angle">文本所在角度</param>
        /// <returns></returns>
        private PointF ConvertTextPoint(PointF text_point, SizeF text_size, float text_angle)
        {
            if (text_angle == 0)
            {
                text_point.Y = text_point.Y - text_size.Height / 2;
            }
            else if (text_angle < 90)
            {

            }
            else if (text_angle == 90)
            {
                text_point.X = text_point.X - text_size.Width / 2;
            }
            else if (text_angle < 180)
            {
                text_point.X = text_point.X - text_size.Width;
            }
            else if (text_angle == 180)
            {
                text_point.Y = text_point.Y - text_size.Height / 2;
                text_point.X = text_point.X - text_size.Width - 4;
            }
            else if (text_angle < 270)
            {
                text_point.Y = text_point.Y - text_size.Height;
                text_point.X = text_point.X - text_size.Width;
            }
            else if (text_angle == 270)
            {
                text_point.Y = text_point.Y - text_size.Height;
                text_point.X = text_point.X - text_size.Width / 2;
            }
            else if (text_angle == 360)
            {
                text_point.Y = text_point.Y - text_size.Height / 2;
                text_point.X = text_point.X + 4;
            }
            else if (text_angle < 360)
            {
                text_point.Y = text_point.Y - text_size.Height;
            }

            return text_point;
        }

        #endregion

        #region 类

        [TypeConverter(typeof(PropertyOrderConverter))]
        public class PlateObject
        {
            private Meter owner = null;
            internal PlateObject(Meter owner) { this.owner = owner; }

            #region 属性

            private int outBorderThickness = 8;
            /// <summary>
            /// 仪表盘外边框厚度
            /// </summary>
            [Description("仪表盘外边框厚度")]
            [PropertyOrder(-192)]
            [DefaultValue(8)]
            public int OutBorderThickness
            {
                get { return this.outBorderThickness; }
                set
                {
                    if (this.outBorderThickness == value || value < 0)
                        return;

                    this.outBorderThickness = value;
                    if (this.owner != null)
                    {
                        this.owner.Invalidate();
                    }
                }
            }

            private int innerBorderThickness = 4;
            /// <summary>
            /// 仪表盘内边框厚度
            /// </summary>
            [Description("仪表盘内边框厚度")]
            [PropertyOrder(-190)]
            [DefaultValue(4)]
            public int InnerBorderThickness
            {
                get { return this.innerBorderThickness; }
                set
                {
                    if (this.innerBorderThickness == value || value < 0)
                        return;

                    this.innerBorderThickness = value;
                    if (this.owner != null)
                    {
                        this.owner.Invalidate();
                    }
                }
            }

            #endregion

        }

        [TypeConverter(typeof(PropertyOrderConverter))]
        public class ArcObject
        {
            private Meter owner = null;
            internal ArcObject(Meter owner) { this.owner = owner; }

            #region 属性

            private bool visible = true;
            /// <summary>
            /// 是否显示弧
            /// </summary>
            [Description("是否显示弧")]
            [PropertyOrder(-190)]
            [DefaultValue(true)]
            public bool Visible
            {
                get { return this.visible; }
                set
                {
                    if (this.visible == value)
                        return;

                    this.visible = value;
                    if (this.owner != null)
                    {
                        this.owner.Invalidate();
                    }
                }
            }

            private int thickness = 8;
            /// <summary>
            /// 厚度
            /// </summary>
            [Description("厚度")]
            [PropertyOrder(-188)]
            [DefaultValue(8)]
            public int Thickness
            {
                get { return this.thickness; }
                set
                {
                    if (this.thickness == value || value < 0)
                        return;

                    this.thickness = value;
                    if (this.owner != null)
                    {
                        this.owner.Invalidate();
                    }
                }
            }

            private int angleSize = 270;
            /// <summary>
            /// 弧度大小
            /// </summary>
            [Description("弧度大小")]
            [PropertyOrder(-182)]
            [DefaultValue(270)]
            public int AngleSize
            {
                get { return this.angleSize; }
                set
                {
                    if (this.angleSize == value || value < 0 || value > 360)
                        return;

                    this.angleSize = value;
                    if (this.owner != null)
                    {
                        this.owner.Invalidate();
                    }
                }
            }

            #endregion

        }

        [TypeConverter(typeof(PropertyOrderConverter))]
        public class GradualArcObject
        {
            private Meter owner = null;
            internal GradualArcObject(Meter owner) { this.owner = owner; }

            #region 属性

            private bool visible = true;
            /// <summary>
            /// 是否显示渐变弧
            /// </summary>
            [Description("是否显示渐变弧")]
            [PropertyOrder(-172)]
            [DefaultValue(true)]
            public bool Visible
            {
                get { return this.visible; }
                set
                {
                    if (this.visible == value)
                        return;

                    this.visible = value;
                    if (this.owner != null)
                    {
                        this.owner.Invalidate();
                    }
                }
            }

            private int thickness = 16;
            /// <summary>
            /// 渐变弧厚度
            /// </summary>
            [Description("渐变弧厚度")]
            [PropertyOrder(-170)]
            [DefaultValue(16)]
            public int Thickness
            {
                get { return this.thickness; }
                set
                {
                    if (this.thickness == value || value < 0)
                        return;

                    this.thickness = value;
                    if (this.owner != null)
                    {
                        this.owner.Invalidate();
                    }
                }
            }

            private MeterGradualColorCollection colorItemsCollection;
            /// <summary>
            /// 渐变弧渐变颜色集合
            /// </summary>
            [Description("渐变弧渐变颜色集合")]
            [PropertyOrder(-168)]
            [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
            public MeterGradualColorCollection ColorItems
            {
                get
                {
                    if (this.colorItemsCollection == null)
                        this.colorItemsCollection = new MeterGradualColorCollection(this.owner);
                    return this.colorItemsCollection;
                }
            }

            #endregion

        }

        [TypeConverter(typeof(PropertyOrderConverter))]
        public class PointerObject
        {
            private Meter owner = null;
            internal PointerObject(Meter owner) { this.owner = owner; }

            #region 属性

            private bool visible = true;
            /// <summary>
            /// 是否显示指针
            /// </summary>
            [Description("是否显示指针")]
            [PropertyOrder(-190)]
            [DefaultValue(true)]
            public bool Visible
            {
                get { return this.visible; }
                set
                {
                    if (this.visible == value)
                        return;

                    this.visible = value;
                    if (this.owner != null)
                    {
                        this.owner.Invalidate();
                    }
                }
            }

            private Size size = new Size(4, 40);
            /// <summary>
            /// 指针Size
            /// </summary>
            [Description("指针Size")]
            [PropertyOrder(-144)]
            [DefaultValue(typeof(Size), "4, 40")]
            public Size Size
            {
                get { return this.size; }
                set
                {
                    if (this.size == value || value.Width < 1 || value.Height < 1)
                        return;

                    this.size = value;
                    if (this.owner != null)
                    {
                        this.owner.Invalidate();
                    }
                }
            }

            #endregion

        }

        [TypeConverter(typeof(PropertyOrderConverter))]
        public class MarkObject
        {
            private Meter owner = null;
            internal MarkObject(Meter owner) { this.owner = owner; }

            #region 属性

            private double mainFrequency = 20D;
            /// <summary>
            /// 主刻度间隔值
            /// </summary>
            [Description("主刻度间隔值")]
            [PropertyOrder(-190)]
            [DefaultValue(20D)]
            public double MainFrequency
            {
                get { return this.mainFrequency; }
                set
                {
                    if (this.mainFrequency == value || value <= 0d)
                        return;

                    this.mainFrequency = value;
                    if (this.owner != null)
                    {
                        this.owner.Invalidate();
                    }
                }
            }

            private Size mainLineSize = new Size(3, 14);
            /// <summary>
            /// 主刻度线Size
            /// </summary>
            [Description("主刻度线Size")]
            [PropertyOrder(-188)]
            [DefaultValue(typeof(Size), "3, 14")]
            public Size MainLineSize
            {
                get { return this.mainLineSize; }
                set
                {
                    if (this.mainLineSize == value || value.Width < 1 || value.Height < 1)
                        return;

                    this.mainLineSize = value;
                    if (this.owner != null)
                    {
                        this.owner.Invalidate();
                    }
                }
            }

            private int mainTextDistance = 10;
            /// <summary>
            /// 主刻度文本与文本间距
            /// </summary>
            [Description("主刻度文本与文本间距")]
            [PropertyOrder(-183)]
            [DefaultValue(10)]
            public int MainTextDistance
            {
                get { return this.mainTextDistance; }
                set
                {
                    if (this.mainTextDistance == value || value < 0)
                        return;

                    this.mainTextDistance = value;
                    if (this.owner != null)
                    {
                        this.owner.Invalidate();
                    }
                }
            }

            private Font mainTextFont = null;
            /// <summary>
            /// 主刻度文本字体
            /// </summary>
            [Description("主刻度文本字体")]
            [PropertyOrder(-172)]
            public Font MainTextFont
            {
                get
                {
                    if (this.mainTextFont != null)
                    {
                        return this.mainTextFont;
                    }
                    if (((Meter)this.owner).Parent != null)
                    {
                        return ((Meter)this.owner).Parent.Font;
                    }
                    return Control.DefaultFont;
                }
                set
                {
                    if (((Meter)this.owner).Parent != null)
                    {
                        if (((Meter)this.owner).Parent.Font.Equals(value))
                        {
                            this.mainTextFont = null;
                            if (this.owner != null)
                            {
                                this.owner.Invalidate();
                            }
                            return;
                        }
                    }
                    if (Control.DefaultFont.Equals(value))
                    {
                        this.mainTextFont = null;
                        if (this.owner != null)
                        {
                            this.owner.Invalidate();
                        }
                        return;
                    }

                    this.mainTextFont = value;
                    if (this.owner != null)
                    {
                        this.owner.Invalidate();
                    }
                }
            }
            private bool ShouldSerializeMainTextFont()
            {
                return (this.mainTextFont != null && !this.mainTextFont.Equals(Control.DefaultFont));
            }
            private void ResetMainTextFont()
            {
                this.mainTextFont = null;
                if (this.owner != null)
                {
                    this.owner.Invalidate();
                }
            }

            private int minorAmount = 1;
            /// <summary>
            /// 一个主刻度分割成多少个子刻度
            /// </summary>
            [Description("一个主刻度分割成多少个子刻度")]
            [PropertyOrder(-148)]
            [DefaultValue(1)]
            public int MinorAmount
            {
                get { return this.minorAmount; }
                set
                {
                    if (value < 1)
                        value = 1;
                    if (this.minorAmount == value)
                        return;

                    this.minorAmount = value;
                    if (this.owner != null)
                    {
                        this.owner.Invalidate();
                    }
                }
            }

            #endregion

        }

        #endregion

        #region 外观

        public class StyleAppearanceObject : AppearanceObjectBase
        {
            internal StyleAppearanceObject(ISkinObject owner, AppearanceObjectBase parent) : base(owner, parent) { }

            #region 属性

            private Color skinBackColor = Color.Empty;
            private readonly Color defaultBackColor = SystemColors.Control;
            private Color backColor = Color.Empty;
            /// <summary>
            /// 背景颜色
            /// </summary>
            [Description("背景颜色")]
            [PropertyOrder(-198)]
            [SkinProperty(true, true)]
            public Color BackColor
            {
                get
                {
                    if (this.owner.GetSkinObjectSkinStateCore() && this.skinBackColor != Color.Empty)
                    {
                        return this.skinBackColor;
                    }

                    if (this.backColor != Color.Empty)
                    {
                        return this.backColor;
                    }

                    if (((Control)this.owner).Parent != null)
                    {
                        return ((Control)this.owner).Parent.BackColor;
                    }

                    return this.defaultBackColor;
                }
                set
                {
                    if (this.backColor == value)
                        return;

                    this.backColor = value;
                    this.Invalidate();
                }
            }
            private bool ShouldSerializeBackColor()
            {
                return this.backColor != Color.Empty;
            }
            private void ResetBackColor()
            {
                this.backColor = Color.Empty;
                this.Invalidate();
            }

            private Color skinTextColor = Color.Empty;
            private readonly Color defaultTextColor = SystemColors.ControlText;
            private Color textColor = Color.Empty;
            /// <summary>
            /// 文本颜色
            /// </summary>
            [Description("文本颜色")]
            [PropertyOrder(-197)]
            [SkinProperty(true, true)]
            public Color TextColor
            {
                get
                {
                    if (this.owner.GetSkinObjectSkinStateCore() && this.skinTextColor != Color.Empty)
                    {
                        return this.skinTextColor;
                    }

                    if (this.textColor != Color.Empty)
                    {
                        return this.textColor;
                    }

                    if (((Control)this.owner).Parent != null)
                    {
                        return ((Control)this.owner).Parent.ForeColor;
                    }

                    return this.defaultTextColor;
                }
                set
                {
                    if (this.textColor == value)
                        return;

                    this.textColor = value;
                    this.Invalidate();
                }
            }
            private bool ShouldSerializeTextColor()
            {
                return this.textColor != Color.Empty;
            }
            private void ResetTextColor()
            {
                this.textColor = Color.Empty;
                this.Invalidate();
            }

            private PlateAppearanceObject plate;
            /// <summary>
            /// 仪表盘
            /// </summary>
            [Description("仪表盘")]
            [PropertyOrder(-195)]
            [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
            [SkinProperty(true, false)]
            public PlateAppearanceObject Plate
            {
                get
                {
                    if (this.plate == null)
                        this.plate = new PlateAppearanceObject(this.owner, this);
                    return this.plate;
                }
            }

            private ArcAppearanceObject arc;
            /// <summary>
            /// 弧
            /// </summary>
            [Description("弧")]
            [PropertyOrder(-194)]
            [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
            [SkinProperty(true, false)]
            public ArcAppearanceObject Arc
            {
                get
                {
                    if (this.arc == null)
                        this.arc = new ArcAppearanceObject(this.owner, this);
                    return this.arc;
                }
            }

            private PointerAppearanceObject pointer;
            /// <summary>
            /// 指针
            /// </summary>
            [Description("指针")]
            [PropertyOrder(-192)]
            [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
            [SkinProperty(true, false)]
            public PointerAppearanceObject Pointer
            {
                get
                {
                    if (this.pointer == null)
                        this.pointer = new PointerAppearanceObject(this.owner, this);
                    return this.pointer;
                }
            }

            private MarkAppearanceObject mark;
            /// <summary>
            /// 刻度
            /// </summary>
            [Description("刻度")]
            [PropertyOrder(-190)]
            [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
            [SkinProperty(true, false)]
            public MarkAppearanceObject Mark
            {
                get
                {
                    if (this.mark == null)
                        this.mark = new MarkAppearanceObject(this.owner, this);
                    return this.mark;
                }
            }

            #endregion

            public class PlateAppearanceObject : AppearanceObjectBase
            {
                internal PlateAppearanceObject(ISkinObject owner, AppearanceObjectBase parent) : base(owner, parent) { }

                #region 属性

                private Color skinBackColor = Color.Empty;
                private readonly Color defaultBackColor = SystemColors.GradientActiveCaption;
                private Color backColor = Color.Empty;
                /// <summary>
                /// 背景颜色
                /// </summary>
                [Description("背景颜色")]
                [PropertyOrder(-198)]
                [SkinProperty(true, false)]
                public Color BackColor
                {
                    get
                    {
                        if (this.owner.GetSkinObjectSkinStateCore())
                        {
                            return this.skinBackColor;
                        }

                        if (this.backColor != Color.Empty)
                        {
                            return this.backColor;
                        }

                        return this.defaultBackColor;
                    }
                    set
                    {
                        if (this.backColor == value)
                            return;

                        this.backColor = value;
                        this.Invalidate();
                    }
                }
                private bool ShouldSerializeBackColor()
                {
                    return this.backColor != Color.Empty;
                }
                private void ResetBackColor()
                {
                    this.backColor = Color.Empty;
                    this.Invalidate();
                }

                private Color skinBackShadowColor = Color.Empty;
                private readonly Color defaultBackShadowColor = SystemColors.GradientInactiveCaption;
                private Color backShadowColor = Color.Empty;
                /// <summary>
                /// 仪表盘背景阴影颜色
                /// </summary>
                [Description("仪表盘背景阴影颜色")]
                [PropertyOrder(-196)]
                [SkinProperty(true, false)]
                public Color BackShadowColor
                {
                    get
                    {
                        if (this.owner.GetSkinObjectSkinStateCore())
                        {
                            return this.skinBackShadowColor;
                        }

                        if (this.backShadowColor != Color.Empty)
                        {
                            return this.backShadowColor;
                        }

                        return this.defaultBackShadowColor;
                    }
                    set
                    {
                        if (this.backShadowColor == value)
                            return;

                        this.backShadowColor = value;
                        this.Invalidate();
                    }
                }
                private bool ShouldSerializeBackShadowColor()
                {
                    return this.backShadowColor != Color.Empty;
                }
                private void ResetBackShadowColor()
                {
                    this.backShadowColor = Color.Empty;
                    this.Invalidate();
                }

                private Color skinOutBorderColor = Color.Empty;
                private readonly Color defaultOutBorderColor = SystemColors.ActiveCaption;
                private Color outBorderColor = Color.Empty;
                /// <summary>
                /// 仪表盘外边框颜色
                /// </summary>
                [Description("仪表盘外边框颜色")]
                [PropertyOrder(-191)]
                [SkinProperty(true, false)]
                public Color OutBorderColor
                {
                    get
                    {
                        if (this.owner.GetSkinObjectSkinStateCore())
                        {
                            return this.skinOutBorderColor;
                        }

                        if (this.outBorderColor != Color.Empty)
                        {
                            return this.outBorderColor;
                        }

                        return this.defaultOutBorderColor;
                    }
                    set
                    {
                        if (this.outBorderColor == value)
                            return;

                        this.outBorderColor = value;
                        this.Invalidate();
                    }
                }
                private bool ShouldSerializeOutBorderColor()
                {
                    return this.outBorderColor != Color.Empty;
                }
                private void ResetOutBorderColor()
                {
                    this.outBorderColor = Color.Empty;
                    this.Invalidate();
                }

                private Color skinInnerBorderColor = Color.Empty;
                private readonly Color defaultInnerBorderColor = SystemColors.ActiveCaption;
                private Color innerBorderColor = Color.Empty;
                /// <summary>
                /// 仪表盘内边框颜色
                /// </summary>
                [Description("仪表盘内边框颜色")]
                [PropertyOrder(-189)]
                [SkinProperty(true, false)]
                public Color InnerBorderColor
                {
                    get
                    {
                        if (this.owner.GetSkinObjectSkinStateCore())
                        {
                            return this.skinInnerBorderColor;
                        }

                        if (this.innerBorderColor != Color.Empty)
                        {
                            return this.innerBorderColor;
                        }

                        return this.defaultInnerBorderColor;
                    }
                    set
                    {
                        if (this.innerBorderColor == value)
                            return;

                        this.innerBorderColor = value;
                        this.Invalidate();
                    }
                }
                private bool ShouldSerializeInnerBorderColor()
                {
                    return this.innerBorderColor != Color.Empty;
                }
                private void ResetInnerBorderColor()
                {
                    this.innerBorderColor = Color.Empty;
                    this.Invalidate();
                }

                #endregion

            }

            public class ArcAppearanceObject : AppearanceObjectBase
            {
                internal ArcAppearanceObject(ISkinObject owner, AppearanceObjectBase parent) : base(owner, parent) { }

                #region 属性

                private Color skinBackColor = Color.Empty;
                private readonly Color defaultBackColor = SystemColors.ControlDarkDark;
                private Color backColor = Color.Empty;
                /// <summary>
                /// 背景颜色
                /// </summary>
                [Description("背景颜色")]
                [PropertyOrder(-158)]
                [SkinProperty(true, false)]
                public Color BackColor
                {
                    get
                    {
                        if (this.owner.GetSkinObjectSkinStateCore())
                        {
                            return this.skinBackColor;
                        }

                        if (this.backColor != Color.Empty)
                        {
                            return this.backColor;
                        }

                        return this.defaultBackColor;
                    }
                    set
                    {
                        if (this.backColor == value)
                            return;

                        this.backColor = value;
                        this.Invalidate();
                    }
                }
                private bool ShouldSerializeBackColor()
                {
                    return this.backColor != Color.Empty;
                }
                private void ResetBackColor()
                {
                    this.backColor = Color.Empty;
                    this.Invalidate();
                }

                private Color skinValueColor = Color.Empty;
                private readonly Color defaultValueColor = SystemColors.Highlight;
                private Color valueColor = Color.Empty;
                /// <summary>
                /// 值颜色
                /// </summary>
                [Description("值颜色")]
                [PropertyOrder(-140)]
                [SkinProperty(true, false)]
                public Color ValueColor
                {
                    get
                    {
                        if (this.owner.GetSkinObjectSkinStateCore())
                        {
                            return this.skinValueColor;
                        }

                        if (this.valueColor != Color.Empty)
                        {
                            return this.valueColor;
                        }

                        return this.defaultValueColor;
                    }
                    set
                    {
                        if (this.valueColor == value)
                            return;

                        this.valueColor = value;
                        this.Invalidate();
                    }
                }
                private bool ShouldSerializeValueColor()
                {
                    return this.valueColor != Color.Empty;
                }
                private void ResetValueColor()
                {
                    this.valueColor = Color.Empty;
                    this.Invalidate();
                }

                #endregion

            }

            public class PointerAppearanceObject : AppearanceObjectBase
            {
                internal PointerAppearanceObject(ISkinObject owner, AppearanceObjectBase parent) : base(owner, parent) { }

                #region 属性

                private Color skinColor = Color.Empty;
                private readonly Color defaultColor = Color.Orange;
                private Color color = Color.Empty;
                /// <summary>
                /// 指针颜色
                /// </summary>
                [Description("指针颜色")]
                [PropertyOrder(-192)]
                [SkinProperty(true, false)]
                public Color Color
                {
                    get
                    {
                        if (this.owner.GetSkinObjectSkinStateCore())
                        {
                            return this.skinColor;
                        }

                        if (this.color != Color.Empty)
                        {
                            return this.color;
                        }

                        return this.defaultColor;
                    }
                    set
                    {
                        if (this.color == value)
                            return;

                        this.color = value;
                        this.Invalidate();
                    }
                }
                private bool ShouldSerializeColor()
                {
                    return this.color != Color.Empty;
                }
                private void ResetColor()
                {
                    this.color = Color.Empty;
                    this.Invalidate();
                }

                private Color skinCapColor = Color.Empty;
                private readonly Color defaultCapColor = SystemColors.Window;
                private Color capColor = Color.Empty;
                /// <summary>
                /// 针帽颜色
                /// </summary>
                [Description("针帽颜色")]
                [PropertyOrder(-180)]
                [SkinProperty(true, false)]
                public Color CapColor
                {
                    get
                    {
                        if (this.owner.GetSkinObjectSkinStateCore())
                        {
                            return this.skinCapColor;
                        }

                        if (this.capColor != Color.Empty)
                        {
                            return this.capColor;
                        }

                        return this.defaultCapColor;
                    }
                    set
                    {
                        if (this.capColor == value)
                            return;

                        this.capColor = value;
                        this.Invalidate();
                    }
                }
                private bool ShouldSerializeCapColor()
                {
                    return this.capColor != Color.Empty;
                }
                private void ResetCapColor()
                {
                    this.capColor = Color.Empty;
                    this.Invalidate();
                }

                private Color skinCapShadowColor = Color.Empty;
                private readonly Color defaultCapShadowColor = SystemColors.Info;
                private Color capShadowColor = Color.Empty;
                /// <summary>
                /// 针帽阴影颜色
                /// </summary>
                [Description("针帽阴影颜色")]
                [PropertyOrder(-170)]
                [SkinProperty(true, false)]
                public Color CapShadowColor
                {
                    get
                    {
                        if (this.owner.GetSkinObjectSkinStateCore())
                        {
                            return this.skinCapShadowColor;
                        }

                        if (this.capShadowColor != Color.Empty)
                        {
                            return this.capShadowColor;
                        }

                        return this.defaultCapShadowColor;
                    }
                    set
                    {
                        if (this.capShadowColor == value)
                            return;

                        this.capShadowColor = value;
                        this.Invalidate();
                    }
                }
                private bool ShouldSerializeCapShadowColor()
                {
                    return this.capShadowColor != Color.Empty;
                }
                private void ResetCapShadowColor()
                {
                    this.capShadowColor = Color.Empty;
                    this.Invalidate();
                }

                #endregion

            }

            public class MarkAppearanceObject : AppearanceObjectBase
            {
                internal MarkAppearanceObject(ISkinObject owner, AppearanceObjectBase parent) : base(owner, parent) { }

                #region 属性

                private Color skinMainLineColor = Color.Empty;
                private readonly Color defaultMainLineColor = SystemColors.ControlDarkDark;
                private Color mainLineColor = Color.Empty;
                /// <summary>
                /// 主刻度线颜色
                /// </summary>
                [Description("主刻度线颜色")]
                [PropertyOrder(-156)]
                [SkinProperty(true, false)]
                public Color MainLineColor
                {
                    get
                    {
                        if (this.owner.GetSkinObjectSkinStateCore())
                        {
                            return this.skinMainLineColor;
                        }

                        if (this.mainLineColor != Color.Empty)
                        {
                            return this.mainLineColor;
                        }

                        return this.defaultMainLineColor;
                    }
                    set
                    {
                        if (this.mainLineColor == value)
                            return;

                        this.mainLineColor = value;
                        this.Invalidate();
                    }
                }
                private bool ShouldSerializeMainLineColor()
                {
                    return this.mainLineColor != Color.Empty;
                }
                private void ResetMainLineColor()
                {
                    this.mainLineColor = Color.Empty;
                    this.Invalidate();
                }

                private Color skinMainTextColor = Color.Empty;
                private readonly Color defaultMainTextColor = SystemColors.ControlText;
                private Color mainTextColor = Color.Empty;
                /// <summary>
                /// 主刻度文本颜色
                /// </summary>
                [Description("主刻度文本颜色")]
                [PropertyOrder(-150)]
                [SkinProperty(true, false)]
                public Color MainTextColor
                {
                    get
                    {
                        if (this.owner.GetSkinObjectSkinStateCore())
                        {
                            return this.skinMainTextColor;
                        }

                        if (this.mainTextColor != Color.Empty)
                        {
                            return this.mainTextColor;
                        }

                        return this.defaultMainTextColor;
                    }
                    set
                    {
                        if (this.mainTextColor == value)
                            return;

                        this.mainTextColor = value;
                        this.Invalidate();
                    }
                }
                private bool ShouldSerializeMainTextColor()
                {
                    return this.mainTextColor != Color.Empty;
                }
                private void ResetMainTextColor()
                {
                    this.mainTextColor = Color.Empty;
                    this.Invalidate();
                }

                private Color skinMinorLineColor = Color.Empty;
                private readonly Color defaultMinorLineColor = SystemColors.ControlLight;
                private Color minorLineColor = Color.Empty;
                /// <summary>
                /// 子刻度颜色
                /// </summary>
                [Description("子刻度颜色")]
                [PropertyOrder(-146)]
                [SkinProperty(true, false)]
                public Color MinorLineColor
                {
                    get
                    {
                        if (this.owner.GetSkinObjectSkinStateCore())
                        {
                            return this.skinMinorLineColor;
                        }

                        if (this.minorLineColor != Color.Empty)
                        {
                            return this.minorLineColor;
                        }

                        return this.defaultMinorLineColor;
                    }
                    set
                    {
                        if (this.minorLineColor == value)
                            return;

                        this.minorLineColor = value;
                        this.Invalidate();
                    }
                }
                private bool ShouldSerializeMinorLineColor()
                {
                    return this.minorLineColor != Color.Empty;
                }
                private void ResetMinorLineColor()
                {
                    this.minorLineColor = Color.Empty;
                    this.Invalidate();
                }

                #endregion

            }

        }

        #endregion

    }

}
